#include "objectview.h"
#include "../application.h"
#include "../document.h"
#include "../mainwindow.h"
#include "../gameobjects/abstractobject.h"
#include <QContextMenuEvent>
#include <QMenu>
#include <QLineEdit>

ObjectView::ObjectView(QWidget *parent) :
    QTreeWidget(parent)
{
    setSelectionMode(QAbstractItemView::SingleSelection);
    setHeaderLabel("Objects");
    setRootIsDecorated(true);

    connect(this, SIGNAL(itemSelectionChanged()), this,
            SLOT(onItemSelectionChanged()));
    connect(this, SIGNAL(itemChanged(QTreeWidgetItem*,int)),
            this, SLOT(onItemChanged(QTreeWidgetItem*,int)));
}

void ObjectView::onObjectCreated(QPointer<AbstractObject> object)
{
    ObjectItem* newItem = new ObjectItem;
    newItem->m_object = object;
    newItem->setText(0, object->id());
    newItem->setFlags(newItem->flags() | Qt::ItemIsEditable);

    if(!object->parentObject())
    {
        addTopLevelItem(newItem);
    }
    else
    {
        QTreeWidgetItemIterator it(this);
        while(*it)
        {
            if(ObjectItem* pMaybeParentObjectItem = dynamic_cast<ObjectItem*>(*it))
            {
                if(pMaybeParentObjectItem->m_object == object->parentObject())
                {
                    pMaybeParentObjectItem->addChild(newItem);
                    pMaybeParentObjectItem->setExpanded(true);
                    break;
                }
            }

            ++it;
        }
    }

    clearSelection();
    newItem->setSelected(true);
}

void ObjectView::onObjectDeleted(QPointer<AbstractObject> object)
{
    QTreeWidgetItemIterator it(this);
    while(*it)
    {
        if(dynamic_cast<ObjectItem*>(*it)->m_object == object)
        {
            if(QTreeWidgetItem* pParent = (*it)->parent())
            {
                QTreeWidgetItem* pToDelete = (*it);
                pParent->removeChild(*it);
                delete pToDelete;

                // TODO: workaround
                clearSelection();
                pParent->setSelected(true);
            }
            else
            {
                int topLevelIndex = indexOfTopLevelItem((*it));
                QTreeWidgetItem* pToDelete = takeTopLevelItem(topLevelIndex);
                delete pToDelete;

                // TODO: workaround
                if(selectedItems().size() > 0 && !selectedItems().first())
                {
                    clearSelection();
                    topLevelItem(0)->setSelected(true);
                }
            }

            break;
        }

        ++it;
    }
}

void ObjectView::selectObject(QPointer<AbstractObject> object)
{
    QTreeWidgetItemIterator it(this);
    while(*it)
    {
        if(ObjectItem* pMaybeSelectedObject = dynamic_cast<ObjectItem*>(*it))
        {
            if(pMaybeSelectedObject->m_object == object)
            {
                clearSelection();
                pMaybeSelectedObject->setSelected(true);
                break;
            }
        }

        ++it;
    }
}

void ObjectView::onItemSelectionChanged()
{
    QList<QTreeWidgetItem*> selList = selectedItems();
    QPointer<AbstractObject> selObject;

    if(selectedItems().size())
    {
        selObject = dynamic_cast<ObjectItem*>(selectedItems().first())->m_object;
    }

    emit objectSelectionChanged(selObject);
}

void ObjectView::onItemChanged(QTreeWidgetItem *item, int column)
{
    ObjectItem* pObjectItem = dynamic_cast<ObjectItem*>(item);
    Q_ASSERT(pObjectItem);
    Q_ASSERT(pObjectItem->m_object);
    pObjectItem->m_object->setID(item->text(0));
}

void ObjectView::contextMenuEvent(QContextMenuEvent *pEvent)
{
    QPoint pos = pEvent->globalPos();
    QTreeWidgetItem* pPreviousSelection = selectedItems().isEmpty() ? 0 : selectedItems().first();
    ObjectItem* pSelItem = dynamic_cast<ObjectItem*>(itemAt(pEvent->pos()));

    QPointer<AbstractObject> selObject;

    if(!pSelItem)
    {
        clearSelection();
    }

    QPointer<QMenu> menu = Application::app().mainWindow()->objectsMenu();
    QAction* pSelectedAction = menu->exec(pos);

    if(!pSelectedAction && !pSelItem && pPreviousSelection)
    {
        // revert to last selected item
        pPreviousSelection->setSelected(true);
    }
}

void ObjectView::keyPressEvent(QKeyEvent *event)
{
    QPointer<Document> doc = Application::app().document();
    Q_ASSERT(doc);

    if(event->key() == Qt::Key_Delete)
    {
        if(!doc->currentObject())
        {
            return;
        }

        doc->deleteObject(doc->currentObject());
        event->accept();
    }
}

void ObjectView::mouseDoubleClickEvent(QMouseEvent *event)
{
    QList<QTreeWidgetItem*> selList = selectedItems();

    if(selList.size())
    {
        QTreeWidgetItem* pSelectedItem = selList.first();
        editItem(pSelectedItem);
    }
}
